#include "sfsis.h"
#include "gd32f1x0.h"
#include "debug.h"
#include "stdio.h"
#define UUID_ADDR 0x1FFFF7AC
/*
接口说明:
底层:LT8920
可拓展并使用其他芯片

*/
#pragma pack(1)
#define SYNCWORDH 0xA3
#define SYNCWORDL 0x80

#define i_setRx() i_spi_w2Byte(7, 0x00, (gChn | 0x80))
#define i_setTx() i_spi_w2Byte(7, 0x01, gChn)
#define i_setIdel() i_spi_w2Byte(7, 0x00, gChn)
#define i_clrFifo() i_spi_w2Byte(52, 0x80, 0x80)
typedef struct
{
    unsigned char addr;
    unsigned char data_h;
    unsigned char data_l;
} LT8920_ConfigReg;
unsigned char gChn = 0;
unsigned const char channelTable[MAX_CHANNEL_NUM] = {
    4, 32, 64, 96, 152, 184, 216, 248
    };

static const LT8920_ConfigReg i_reg[] =
    {
        {0, 0x6f, 0xe0}, //-- 6fe0(Recommand)(6fef = default)
        {1, 0x56, 0x81},
        {2, 0x66, 0x17},
        {4, 0x9c, 0xc9},
        {5, 0x66, 0x37},
        {7, 0x00, 0x30}, //channel is 2402Mhz
        {8, 0x6c, 0x90},
        {9, 0x48, 0x00}, //PA -12.2dbm,1840?
        {10, 0x7f, 0xfd},
        {11, 0x00, 0x08},
        {12, 0x00, 0x00},
        {13, 0x48, 0xbd},
        {22, 0x00, 0xff},
        {23, 0x80, 0x05},
        {24, 0x00, 0x67},
        {25, 0x16, 0x59},
        {26, 0x19, 0xe0},
        {27, 0x13, 0x00},
        {28, 0x18, 0x00},
        {32, 0x48, 0x00}, //tail 3 byte,sync word 32bit(REG36 REG39)
        {33, 0x3f, 0xc7},
        {34, 0x20, 0x00},
        {35, 0x04, 0x00}, //-- ReSend Timer=10?4?
        /*sync word*/
        {36, SYNCWORDH, SYNCWORDL},
        {37, 0xA3, 0x80},
        {38, 0xA5, 0x5A},
        {39, 0xA3, 0x80},
        {40, 0x44, 0x03},
        {41, 0xBC, 0x00}, /*CRC is ON, scramble is OFF, AUTO_ACK  Enable, PKT Low Active*/
        {42, 0xFD, 0xb0}, /*??RX_ACK?? 176us*/
        {43, 0x00, 0x0f},
        {44, 0x04, 0x00}, //{44, 0x01, 0x00}, //250Kbps
        {45, 0x05, 0x52},
        {50, 0x00, 0x00}};
#define CONFIG_REG_SIZE (sizeof(i_reg) / sizeof(LT8920_ConfigReg))
#pragma pack()
void i_spi_w2Byte(unsigned char address, unsigned char msByte, unsigned char lsByte)
{
    unsigned char txBuf[2];
    txBuf[0] = address;
    hwl_spi_SS_reset();
    hwl_spi_TxMultByte(txBuf, 1);
    txBuf[0] = msByte;
    txBuf[1] = lsByte;
    hwl_spi_TxMultByte(txBuf, 2);
    hwl_spi_SS_set();
}

void i_spi_r2Byte(unsigned char address, unsigned char *msbyte, unsigned char *lsbyte)
{
    unsigned char buf[2];
    hwl_spi_SS_reset();
    buf[0] = address | 0x80;
    hwl_spi_TxMultByte(buf, 1);
    hwl_spi_RxMultByte(buf, 2);
    hwl_spi_SS_set();
    *lsbyte = buf[1];
    *msbyte = buf[0];
}

void i_writeFifo(unsigned char *buf, unsigned char len)
{
    unsigned char txBuf[1];
    if (len > 63)
    {
        len = 63;
    }

    //写地址 50地址 为fifo
    hwl_spi_SS_reset();
    txBuf[0] = 50;
    hwl_spi_TxMultByte(txBuf, 1);

    //写长度
    txBuf[0] = len;
    hwl_spi_TxMultByte(txBuf, 1);
    //写数据
    hwl_spi_TxMultByte(buf, len);
    hwl_spi_SS_set();
}

unsigned char i_readFifo(unsigned char *buf, unsigned char bufLen)
{
    unsigned char ibuf[1];
    unsigned char ret;
    if (bufLen > 63)
    {
        bufLen = 63;
    }

    hwl_spi_SS_reset();

    //读fifo地址
    ibuf[0] = 0xB2; // = 50 | 0x80
    hwl_spi_TxMultByte(ibuf, 1);
    //读fifo的值，第一个值为数据长度
    if (hwl_spi_RxMultByte(ibuf, 1) == SF_False)
    {
        DPRINT(DEBUG_ERROR, "[BSF INTERFACE] READ FIFO ERROR! can't read length.\r\n");
        return 0;
    }
    ret = ibuf[0];

    if (ret > bufLen)
    {
        ret = bufLen;
    }

    hwl_spi_RxMultByte(buf, ret);
    hwl_spi_SS_set();

    return ret;
}
void bsf_itf_init(void)
{
    unsigned char retryCnt = 20;
    unsigned char value[10] = {0xFF, 0xFF};
    unsigned int ii = 0;

    hwl_spi_init();
    hwl_gpio_set(HWL_PIN_LT8920_PKT, HWL_INPUT);
    hwl_gpio_set(HWL_PIN_LT8920_RST, HWL_OUTPUT);

    hwl_gpio_set(HWL_PIN_LT8920_RST, HWL_LOW);
    hwl_delay_ms(100);
    hwl_gpio_set(HWL_PIN_LT8920_RST, HWL_HIGH);
    hwl_delay_ms(500);

    while (retryCnt--)
    {
        value[1] = 0xFF;
        value[0] = 0xFF;
        i_spi_r2Byte(9, &value[1], &value[0]);
        if (value[1] == 0x48 && value[0] == 0x00)
        {
            DPRINT(DEBUG_INFO, "[BSF INTERFACE] devcie hardware OK!\r\n");
            break;
        }
        else
        {
            DPRINT(DEBUG_ERROR, "[BSF INTERFACE] device hardware ERROR!\r\n");
        }
        hwl_delay_ms(10);
    }

    if (retryCnt == 0)
    {
        DPRINT(DEBUG_ERROR, "[BSF INTERFACE] init failed!\r\n");
    }

    DPRINT(DEBUG_INFO, "[BSF INTERFACE]flushing regs.");

    for (ii = 0; ii < CONFIG_REG_SIZE; ii++)
    {
        i_spi_w2Byte(i_reg[ii].addr, i_reg[ii].data_h, i_reg[ii].data_l);
        i_spi_r2Byte(i_reg[ii].addr, &value[1], &value[0]);
        if ((value[1] != i_reg[ii].data_h) || (value[0] != i_reg[ii].data_l))
        {
            if (i_reg[ii].addr == 0x2c)
            {
                continue; //2c地址即使设置了，官方也会复位
            }
            else
            {
                DPRINT(DEBUG_WARN, "\n[BSF INTERFACE] register not match:addr:0x%x write:0x%x,0x%x, read:0x%x,0x%x", i_reg[ii].addr, i_reg[ii].data_h, i_reg[ii].data_l, value[1], value[0]);
            }
        }
        else
        {
            DPRINT(DEBUG_INFO, ".");
        }
    }
    DPRINT(DEBUG_INFO, "Finished.\r\n");

    DPRINT(DEBUG_INFO, "[BSF INTERFACE] Fifo Testing");
    i_setIdel();
    i_clrFifo();
    for (ii = 0; ii < sizeof(value); ii++)
    {
        value[ii] = ii;
    }
    hwl_delay_us(10);
    i_writeFifo(value, sizeof(value));
    for (ii = 0; ii < sizeof(value); ii++)
    {
        value[ii] = 0;
    }
    i_readFifo(value, sizeof(value));
    for (ii = 0; ii < sizeof(value); ii++)
    {
        if (value[ii] != ii)
        {
            DPRINT(DEBUG_INFO, "Failed! read write not match.");
            break;
        }
        else
        {
            DPRINT(DEBUG_INFO,".");
        }
    }
    DPRINT(DEBUG_INFO,"Finished.\r\n");
    bsf_itf_setChn(0);
    i_clrFifo();
    i_setRx();
}
void bsf_itf_save(unsigned char addr, unsigned char *buf, unsigned char buflen)
{
    unsigned int ii = 0;
    if (buflen > 8)
    {
        buflen = 8;
    }
    for (ii = 0; ii < buflen; ii++)
    {
        gCfgWirelessPtr->regs[ii] = buf[ii];
    }
    config_flush(CONFIG_WIRELESS);
}

void bsf_itf_read(unsigned char addr, unsigned char len, unsigned char *buf)
{
    unsigned int ii = 0;
    for (ii = 0; ii < len; ii++)
    {
        buf[ii] = config_getReg(CONFIG_MAP_WIRELESS_HEAD + addr + ii);
    }
}

void bsf_itf_send(unsigned char *buf, unsigned char datLen)
{
    unsigned char ii = 0;
    i_setIdel();
    i_clrFifo();
    hwl_delay_us(5);
    i_writeFifo(buf, datLen);
    hwl_delay_us(5);
    i_setTx();
    hwl_delay_us(5);
    while (hwl_gpio_get(HWL_PIN_LT8920_PKT) == HWL_HIGH)
    {
        ii++;
        hwl_delay_us(500);
        if (ii > 100) //50ms无反应直接跳出循环
        {
            //todo err print
            break;
        }
    }
}

unsigned char bsf_itf_recv(unsigned char *buf, unsigned char bufLen)
{
    unsigned char ret;
    i_setIdel();
    ret = i_readFifo(buf, bufLen);
    i_clrFifo();
    i_setRx();
    hwl_delay_us(10);
    return ret;
}

unsigned char bsf_itf_isRecvArrival()
{
    if (hwl_gpio_get(HWL_PIN_LT8920_PKT) == HWL_LOW)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

void bsf_itf_setChn(unsigned char chn)
{
    i_setIdel();
    hwl_delay_us(10);
    i_clrFifo();
    gChn = chn;
}

void bsf_itf_setToRx(void)
{
    i_setIdel();
    i_clrFifo();
    i_setRx();
    hwl_delay_us(10);
}

void bsf_itf_setSync(unsigned char uuid[2])
{
    i_setIdel();
    hwl_delay_us(10);
    i_spi_w2Byte(36, (unsigned char)uuid[1], (unsigned char)uuid[0]);
    i_setIdel();
    hwl_delay_us(10);
    i_setRx();
    hwl_delay_us(10);
}

void bsf_itf_setSyncDefault(void)
{
    i_setIdel();
    hwl_delay_us(10);
    i_spi_w2Byte(36, SYNCWORDH, SYNCWORDL); //默认同步字
    i_setIdel();
    hwl_delay_us(10);
    i_setRx();
    hwl_delay_us(10);
}

unsigned short int bsf_itf_getUID(void)
{
    unsigned long id = *((unsigned long *)UUID_ADDR);
    return (unsigned short)id;
}
